package com.chensi.admin.shop.service.impl;

import com.chensi.admin.shop.common.BaseErrorCode;
import com.chensi.admin.shop.domain.Goods;
import com.chensi.admin.shop.domain.GoodsUnit;
import com.chensi.admin.shop.dto.GoodsDTO;
import com.chensi.admin.shop.service.GoodsService;
import com.chensi.admin.shop.util.BeanUtils;
import com.chensi.admin.shop.util.CommonUtil;
import com.chensi.admin.shop.util.SpecificationUtil;
import com.chensi.admin.shop.dao.GoodsUnitRepository;
import com.chensi.admin.shop.exception.BaseException;
import com.chensi.admin.shop.service.GoodsUnitService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author si.chen
 * @date 2019/7/15 17:11
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class GoodsUnitServiceImpl implements GoodsUnitService {

    private final GoodsUnitRepository goodsUnitRepository;

    private final GoodsService goodsService;

    @Autowired
    public GoodsUnitServiceImpl(GoodsUnitRepository goodsUnitRepository, GoodsService goodsService) {
        this.goodsUnitRepository = goodsUnitRepository;
        this.goodsService = goodsService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(GoodsUnit entity) throws BaseException {
        this.checkUniqueForCreate(entity);
        goodsUnitRepository.save(entity);
    }

    @Override
    public List<GoodsUnit> list(GoodsUnit entity) {
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        return goodsUnitRepository.findAll(this.getSpecification(entity), sort);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(GoodsUnit goodsUnit) throws BaseException {
        GoodsUnit entity = this.get(goodsUnit.getId());
        BeanUtils.copyNotNullProperties(goodsUnit, entity);
        this.checkUniqueForUpdate(entity);
        goodsUnitRepository.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) throws BaseException {
        //判断是否存在关联对象
        Goods param = new Goods();
        GoodsUnit goodsUnit = new GoodsUnit();
        goodsUnit.setId(id);
        param.setGoodsUnit(goodsUnit);
        List<GoodsDTO> list = goodsService.list(param);
        if (CommonUtil.isNotEmptyList(list)) {
            throw new BaseException(BaseErrorCode.NOT_DELETE_IN_USE);
        } else {
            GoodsUnit entity = this.get(id);
            goodsUnitRepository.delete(entity);
        }
    }

    @Override
    public GoodsUnit get(String id) throws BaseException {
        Optional<GoodsUnit> optional = goodsUnitRepository.findById(id);
        return optional.orElseThrow(() -> new BaseException(BaseErrorCode.ITEM_NOT_FOUND));
    }

    private void checkUniqueForCreate(GoodsUnit entity) throws BaseException {
        if (StringUtils.isNotBlank(entity.getName())) {
            GoodsUnit param = new GoodsUnit();
            param.setName(entity.getName());
            if (CommonUtil.isNotEmptyList(this.list(param))) {
                throw new BaseException(BaseErrorCode.NAME_IS_USED);
            }
        }
    }

    @SuppressWarnings("Duplicates")
    private void checkUniqueForUpdate(GoodsUnit entity) throws BaseException {
        if (StringUtils.isNotBlank(entity.getName())) {
            GoodsUnit param = new GoodsUnit();
            param.setName(entity.getName().trim());
            param.setIdNe(entity.getId());
            if (CommonUtil.isNotEmptyList(this.list(param))) {
                throw new BaseException(BaseErrorCode.NAME_IS_USED);
            }
        }
    }

    @SuppressWarnings("Duplicates")
    private Specification<GoodsUnit> getSpecification(GoodsUnit entity) {
        return (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            SpecificationUtil.baseSpecification(root, cb, list, entity);
            if (StringUtils.isNotBlank(entity.getName())) {
                Predicate predicate = cb.equal(root.get("name"), entity.getName().trim());
                list.add(predicate);
            }
            query.where(list.toArray(new Predicate[0]));
            return query.getRestriction();
        };
    }
}
